if ENEIDA_UTIL_INCLUDE = 'DATA'

; private data
align 4
_image_header           db 0, 0, 2, 13 dup 0, 32, 0

align 16
_image_conv_mask_i8     db 0, 4, 8, 12, 12 dup 0x80
_image_0                dd 4 dup 0
_image_1_f32            dd 4 dup 1.0
_image_255_f32          dd 4 dup 255.0

else if ENEIDA_UTIL_INCLUDE = 'CODE'

; Allocate memory storage for the image.
;
; [in, int, rdi] alloc size in bytes
; [out, void *, rax] pointer to allocated data
image_alloc:
    mov eax,9           ; sys_map
    mov esi,0           ; addr
    xchg rsi,rdi        ; length (esi)
    mov edx,0x1+0x2     ; prot = PROT_READ | PROT_WRITE
    mov r10d,0x02+0x20  ; flags = MAP_PRIVATE | MAP_ANONYMOUS
    mov r8,-1           ; fd
    mov r9d,0           ; offset
    syscall
    ret

; Save image to the file.
;
; [in, const char *, rdi] pointer to file name
; [in, const void *, rsi] pointer to pixel data
; [in, int, rdx] image width in pixels
; [in, int, rcx] image height in pixels
image_save:
    push rbp
    mov rbp,rsp
    sub rsp,40
    mov [rbp-40],rdi
    mov [rbp-32],rsi
    mov [rbp-24],rdx
    mov [rbp-16],rcx
    ; create TGA file
    mov	eax,85
    mov	rdi,[rbp-40]
    mov esi,110000000b
    syscall
    mov [rbp-8],rax
    ; write TGA header
    mov ax,[rbp-24]
    mov word [_image_header+12],ax
    mov ax,[rbp-16]
    mov word [_image_header+14],ax
    mov eax,1
    mov rdi,[rbp-8]
    mov rsi,_image_header
    mov edx,18
    syscall
    ; write TGA pixel data
    mov eax,[rbp-24]
    mul dword [rbp-16]
    shl eax,2
    mov edx,eax
    mov eax,1
    mov rdi,[rbp-8]
    mov rsi,[rbp-32]
    syscall
    mov rsp,rbp
    pop rbp
    ret

; Convert image from ARGB32F format to ARGB8.
;
; [in, void *, rdi] pointer to dst pixel data (LDR)
; [in, const void *, rsi] pointer to src pixel data (HDR)
; [in, int, rdx] image width in pixels
; [in, int, rcx] image height in pixels
image_hdr2ldr:
    mov eax,edx
    mul ecx
    mov ecx,eax
    movaps xmm1,dqword [_image_255_f32]
    movaps xmm2,dqword [_image_conv_mask_i8]
    movaps xmm3,dqword [_image_0]
    movaps xmm4,dqword [_image_1_f32]
    mov eax,0xff000000
    movd xmm5,eax
      .convert:
    ; clamp to [0.0; 1.0]
    movaps xmm0,[rsi]
    maxps xmm0,xmm3
    minps xmm0,xmm4
    ; convert from [0.0; 1.0] to [0; 255]
    mulps xmm0,xmm1
    cvttps2dq xmm0,xmm0
    pshufb xmm0,xmm2
    por xmm0,xmm5      ; set alpha to 0xff
    movd [rdi],xmm0
    add rsi,16
    add rdi,4
    sub ecx,1
    jnz .convert
    ret

end if
